﻿namespace LoveMusic
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Drawing;
    using System.Globalization;
    using System.IO;
    using System.Net;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Web.Mvc;
    using System.Web.Security;
    using System.Xml;
    using LoveMusic.Helpers;
    using LoveMusic.Models;

    /// <summary>
    /// Handles all story related operation.
    /// </summary>
    public class SongController : BaseController, IDisposable
    {
        #region private

        private static readonly Regex UrlExpression = new Regex(@"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", RegexOptions.Compiled | RegexOptions.Singleline);
        private static readonly int _storyPerPage;
        private int _songFormat = 1;
        private static readonly int _topTags;
        private static readonly int _qualifyingLove;
        private static int _weight = 10000;
        private readonly IDataContext _dataContext;

        private IDataContext DataContext
        {
            [System.Diagnostics.DebuggerStepThrough]
            get
            {
                return _dataContext;
            }
        }

        /// <summary>
        /// Initializes the <see cref="SongController"/> class.
        /// </summary>
        static SongController()
        {
            var settings = ConfigurationManager.GetSection("storySettings") as Hashtable;

            if (settings != null)
            {
                _storyPerPage = Convert.ToInt32(settings["storyPerPage"], CultureInfo.InvariantCulture);
                _topTags = Convert.ToInt32(settings["topTags"], CultureInfo.InvariantCulture);
                _qualifyingLove = Convert.ToInt32(settings["qualifyingLove"], CultureInfo.InvariantCulture);
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SongController"/> class.
        /// </summary>
        /// <param name="dataContext">The data context.</param>
        /// <param name="userManager">The membership provider that will be used.</param>
        public SongController(IDataContext dataContext, MembershipProvider userManager)
            : base(userManager)
        {
            _dataContext = dataContext;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SongController"/> class.
        /// </summary>
        public SongController()
            : this(new ModelDataContext(), Membership.Provider)
        {
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        [NonAction]
        public void Dispose()
        {
            if (_dataContext != null)
            {
                _dataContext.Dispose();
            }
        }

        #endregion

        [CompressFilter]
        public ActionResult TopPopular2010LoveSongs(int? page)
        {
            var viewData = GetStoryListViewData<StoryListByCategoryData>(page);
            var total = 0;
            string moodList = "Romantic";

            viewData.Stories = DataContext.SearchMoods(moodList, _weight, CurrentUserId, CalculateStartIndex(page), _storyPerPage, out total);

            viewData = FillSongsForMp3Player(viewData);
            viewData.Category = "Top popular 2010 love songs";

            viewData.StoryCount = total;
            return View("TopPopular2010LoveSongs", viewData);
        }

        [CompressFilter]
        public ActionResult TopPopularLoveSongs(int? page)
        {
            var viewData = GetStoryListViewData<StoryListByCategoryData>(page);
            var total = 0;
            string moodList = "Thoughtful or Stately or Hopeful or Greasy";

            viewData.Stories = DataContext.SearchMoods(moodList, _weight, CurrentUserId, CalculateStartIndex(page), _storyPerPage, out total);

            viewData = FillSongsForMp3Player(viewData);
            viewData.Category = "love";

            viewData.StoryCount = total;
            return View("TopPopular2010LoveSongs", viewData);
        }


        /// <summary>
        /// To be done
        /// </summary>
        /// <param name="page"></param>
        /// <param name="q"></param>
        /// <returns></returns>
        [CompressFilter]
        public ActionResult ShowMeTheSongs(int? page, string q)
        {
            var viewData = GetStoryListViewData<StoryListByCategoryData>(page);
            return View("TopPopularLoveSongs", viewData);
        }

        /// <summary>
        /// List songs for the weather of the visitor
        /// </summary>
        /// <param name="name"></param>
        /// <param name="page"></param>
        /// <returns></returns>
        [CompressFilter]
        [OutputCache(Duration = 60, VaryByParam = "name;page")]
        public ActionResult CategoryWeather(string name, int? page)
        {
            string VisitorsIPAddr = string.Empty;
            string locationUrl = "http://www.ipgp.net/api/xml/";
            WeatherInformation wi = null;
            VisitorInformation vi = null;
            //Users IP Address.       
            try
            {
                VisitorsIPAddr = Request.ServerVariables["REMOTE_ADDR"];
#if DEBUG
                VisitorsIPAddr = "195.26.158.190"; //Mk
                //   VisitorsIPAddr = "65.183.6.8"; //Jamaica
                if (VisitorsIPAddr == null || VisitorsIPAddr == "127.0.0.1")
                    return RedirectToAction("Category");
#else

                    
                    if (VisitorsIPAddr == null )
                        return RedirectToAction("Category");

#endif

                locationUrl = locationUrl + VisitorsIPAddr;

                #region Get xml data for country

                string xml = WebHelper.GetResponseStandard(locationUrl);


                if (xml != null)
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(new StringReader(xml));

                    if (xmlDoc != null)
                    {
                        vi = new VisitorInformation()
                        {
                            Ip = xmlDoc.GetElementsByTagName("Ip").Item(0).InnerXml,
                            Code = xmlDoc.GetElementsByTagName("Code").Item(0).InnerXml,
                            Country = xmlDoc.GetElementsByTagName("Country").Item(0).InnerXml,
                            Flag = xmlDoc.GetElementsByTagName("Flag").Item(0).InnerXml,
                            City = xmlDoc.GetElementsByTagName("City").Item(0).InnerXml,
                            Region = xmlDoc.GetElementsByTagName("Region").Item(0).InnerXml,
                            Isp = xmlDoc.GetElementsByTagName("Isp").Item(0).InnerXml,
                            Lat = xmlDoc.GetElementsByTagName("Lat").Item(0).InnerXml,
                            Lng = xmlDoc.GetElementsByTagName("Lng").Item(0).InnerXml,
                        };
                    }
                }


                #endregion

                #region Get weather from google api


                if (vi != null)
                {
                    string weatherUrl = "http://www.google.com/ig/api?weather=" + vi.City;
                    xml = WebHelper.GetResponseStandard(weatherUrl);
                    if (xml != null)
                    {
                        XmlDocument xmlDoc = new XmlDocument();
                        xmlDoc.Load(new StringReader(xml));

                        if (xmlDoc != null)
                        {
                            foreach (XmlElement element in xmlDoc.GetElementsByTagName("current_conditions"))
                            {
                                wi = new WeatherInformation()
                                {
                                    Condition = element.ChildNodes[0].Attributes[0].Value,
                                    Temp_f = element.ChildNodes[1].Attributes[0].Value,
                                    Temp_c = element.ChildNodes[2].Attributes[0].Value,
                                    Humidity = element.ChildNodes[3].Attributes[0].Value,
                                    IconUrl = "http://www.google.com" + element.ChildNodes[4].Attributes[0].Value,
                                    Wind_condition = element.ChildNodes[5].Attributes[0].Value
                                };
                                //weather = element.ChildNodes[0].Attributes[0].Value;
                            }
                        }
                    }
                }

                #endregion
            }
            catch (Exception e)
            {
                return RedirectToAction("Category");
            }

            var viewData = GetStoryListViewData<StoryListByCategoryData>(page);
            var total = 0;
            string moodList = string.Empty;
            string logicalOperator = " or ";

            #region get artists with moods similar to weather

#if DEBUG
            // wi.Condition = "Haze";
#endif

            Stack s = new Stack(6);

            switch (wi.Condition)
            {
                case "Clear":
                    s.Push("Ethereal");
                    s.Push("Soothing");
                    s.Push("Eerie");
                    s.Push("Atmospheric");
                    s.Push("Summery");
                    s.Push("Happy");

                    break;
                case "Cloudy":
                    s.Push("Volatile");
                    s.Push("Summery");
                    s.Push("Eerie");
                    s.Push("Atmospheric");
                    s.Push("Slick");
                    s.Push("Relaxed");

                    break;
                case "Fog":
                    s.Push("Acerbic");
                    s.Push("Ominous");
                    s.Push("Nocturnal");
                    s.Push("Hedonistic");
                    s.Push("Hypnotic");
                    s.Push("Hostile");
                    break;
                case "Haze":
                    s.Push("Swaggering");
                    s.Push("Sophisticated");
                    s.Push("Elegant");
                    s.Push("Detached");
                    s.Push("Cathartic");
                    s.Push("Bittersweet");
                    break;
                case "Light Rain":
                    s.Push("Precious");
                    s.Push("Wistful");
                    s.Push("Romantic");
                    s.Push("Bright");
                    s.Push("Wry");
                    s.Push("Autumnal");
                    break;
                case "Mostly Cloudy":
                    s.Push("Precious");
                    s.Push("Wistful");
                    s.Push("Romantic");
                    s.Push("Naive");
                    s.Push("Weary");
                    s.Push("Trashy");
                    break;

                    // SAD Hurt jonny cash....
                    //s.Push("Indulgent");
                    //s.Push("Dramatic");
                    //s.Push("Trippy");
                    //s.Push("Hypnotic");
                    //s.Push("Brash");
                    //s.Push("Druggy");
                    break;

                case "Overcast":
                    s.Push("Organic");
                    s.Push("Indulgent");
                    s.Push("Dramatic");
                    s.Push("Trippy");
                    s.Push("Brash");
                    s.Push("Hypnotic");
                    break;
                case "Partly Cloudy": // Relativily happy weather needs uplifting happy music
                    s.Push("Exciting");
                    s.Push("Springlike");
                    s.Push("Silly");
                    s.Push("Giddy");
                    s.Push("Spicy");
                    s.Push("Lazy");
                    break;
                case "Rain":
                    s.Push("Silly");
                    s.Push("Detached");
                    s.Push("Autumnal");
                    s.Push("Atmospheric");
                    s.Push("Sleazy");
                    s.Push("Harsh");
                    break;

                case "Rain Showers":
                    s.Push("Detached");
                    s.Push("Autumnal");
                    s.Push("Sleazy");
                    s.Push("Harsh");
                    s.Push("Delicate");
                    s.Push("Gentle");
                    break;

                case "Showers":
                    s.Push("Detached");
                    s.Push("Autumnal");
                    s.Push("Sleazy");
                    s.Push("Harsh");
                    s.Push("Delicate");
                    s.Push("Bravado");
                    break;

                case "Thunderstorm":
                    //s.Push("Detached");
                    s.Push("Autumnal");
                    s.Push("Sleazy");
                    s.Push("Harsh");
                    s.Push("Delicate");
                    s.Push("Outrageous");
                    s.Push("Volatile");

                    break;
                case "Snow":
                    s.Push("Wintry");
                    s.Push("Insular");
                    s.Push("Meandering");
                    s.Push("Cold");
                    s.Push("Soft");
                    s.Push("Thoughtful");
                    break;
                case "Light snow":

                    s.Push("Meandering");
                    s.Push("Street-Smart");
                    s.Push("Thoughtful");
                    s.Push("Insular");
                    s.Push("Cold");
                    s.Push("Soft");
                    break;
                case "Chance of Snow":
                    s.Push("Wintry");
                    s.Push("Thoughtful");
                    s.Push("Insular");
                    s.Push("Meandering");
                    s.Push("Cold");
                    s.Push("Soft");
                    break;
                case "Chance of Showers":
                    s.Push("Autumnal");
                    s.Push("Thoughtful");
                    s.Push("Insular");
                    s.Push("Meandering");
                    s.Push("Weary");
                    s.Push("Hedonistic");
                    break;


                case "Scattered Showers":
                    s.Push("Autumnal");
                    s.Push("Thoughtful");
                    s.Push("Weary");
                    s.Push("Hedonistic");
                    s.Push("Precious");
                    s.Push("Hopeful");
                    break;

                case "Mostly Sunny":
                    s.Push("Crunchy");
                    s.Push("Bright");
                    s.Push("Warm");
                    s.Push("Joyous");
                    s.Push("Summery");
                    s.Push("Spicy");
                    break;

                case "Partly Sunny":
                    s.Push("Crunchy");
                    s.Push("Bright");
                    s.Push("Warm");
                    s.Push("Joyous");
                    s.Push("Summery");
                    s.Push("Spicy");
                    break;
                case "Sunny":
                    s.Push("Crunchy");
                    s.Push("Bright");
                    s.Push("Warm");
                    s.Push("Summery");
                    s.Push("Spicy");
                    s.Push("Effervescent");
                    break;


                default:
                    s.Push("Joyous");
                    s.Push("Crunchy");
                    s.Push("Bright");
                    s.Push("Warm");
                    s.Push("Summery");
                    s.Push("Spicy");
                    s.Push("Effervescent");
                    break;

            }

            int getCatNumber;



            #endregion

            if (string.IsNullOrEmpty(name))
            {
                getCatNumber = 2;
                for (int i = 0; i < getCatNumber; i++)
                {
                    if (i == getCatNumber - 1)//Last circle
                        logicalOperator = string.Empty;
                    moodList = moodList + (s.Pop() as string) + logicalOperator;
                }

                viewData.Stories = DataContext.SearchMoods(moodList, _weight, CurrentUserId, CalculateStartIndex(page), 100, out total);
                name = "All";
            }
            else
            {//Category specific
                getCatNumber = GetCategoryNumber(name);


                for (int i = 0; i < getCatNumber; i++)
                {
                    if (i == getCatNumber - 1)//Last circle
                        logicalOperator = string.Empty;
                    moodList = moodList + (s.Pop() as string) + logicalOperator;
                }

                name = name.UrlDecode();

                var category = DataContext.GetCategoryByName(name);

                if (category != null)
                {
                    viewData.Stories = DataContext.GetSongsMoodsCategory(moodList, CurrentUserId, category.ID, CalculateStartIndex(page), _storyPerPage, out total);
                    viewData.CategoryID = category.ID;
                }
            }



            viewData = FillSongsForMp3Player(viewData);
            viewData.Category = name;

            viewData.StoryCount = total;
            viewData.VisitorInfo = vi;
            viewData.WeatherInfo = wi;

            return View("CategoryWeather", viewData);


        }

        /// <summary>
        /// List published stories of both all category and specific category
        /// </summary>
        /// <param name="name">The category name. If the parameter is blank it shows all the stories regarless the category.</param>
        /// <param name="page">The page number (1 based). If not specifed then shows the first page.</param>
        [CompressFilter]
        [OutputCache(Duration = Int32.MaxValue, VaryByParam = "name;page")]
        public ActionResult Category(string name, int? page)
        {
            var viewData = GetStoryListViewData<StoryListByCategoryData>(page);
            var total = 0;

            if (string.IsNullOrEmpty(name))
            {
                viewData.Stories = DataContext.GetSongsForAllCategory(CurrentUserId, CalculateStartIndex(page), 100, out total);
                name = "All";
            }
            else
            {
                name = name.UrlDecode();

                var category = DataContext.GetCategoryByName(name);

                if (category != null)
                {
                    viewData.Stories = DataContext.GetSongsForCategory(CurrentUserId, category.ID, CalculateStartIndex(page), _storyPerPage, out total);
                    viewData.CategoryID = category.ID;
                }
            }

            viewData = FillSongsForMp3Player(viewData);
            viewData.Category = name;
            viewData.StoryCount = total;

            return View("Category", viewData);
        }

        /// <summary>
        /// Helper method that fills the viewadata playlist and title used in category and categoryweather
        /// </summary>
        /// <param name="viewData"></param>
        /// <returns></returns>
        private StoryListByCategoryData FillSongsForMp3Player(StoryListByCategoryData viewData)
        {
            viewData.PlayListYouTube = new List<string>();

            string playlistUrl = string.Empty;
            string playlistTitle = string.Empty;
            List<string> playListYouTube = new List<string>();

            int songNumber = 0;
            if (viewData.Stories.Length > 0)
            {
                #region First Song And Youtube Clip

                if (viewData.Stories[0].Mp3Files != null && viewData.Stories[0].Mp3Files.Length > 0)
                {
                    playlistUrl = "/Song/GetStreamMp3/" + viewData.Stories[0].Mp3Files[0].Mp3File_ID.ToString() + "/" + viewData.Stories[0].ID.ToString() + "|";
                    playlistTitle = WebHelper.RemoveSpecialCharactersExceptTire(viewData.Stories[0].Mp3Files[0].Title) + "|";

                    songNumber++;
                }
                if (viewData.Stories[0].YouTubeID != null && viewData.Stories[0].YouTubeID != string.Empty && !playListYouTube.Contains(viewData.Stories[0].YouTubeID))
                    playListYouTube.Add(viewData.Stories[0].YouTubeID);
                #endregion

                #region Adds all other songs to their playlists.

                foreach (var story in viewData.Stories)
                {
                    if (story.Mp3Files != null && story.Mp3Files.Length > 0 && songNumber > 1)
                    {
                        Mp3FileItem v = story.Mp3Files[0];//take first
                        playlistUrl = playlistUrl + "/Song/GetStreamMp3/" + v.Mp3File_ID.ToString() + "/" + story.ID.ToString() + "|";
                        playlistTitle = playlistTitle + WebHelper.RemoveSpecialCharactersExceptTire(v.Title) + "|";
                    }
                    if (story.YouTubeID != null && story.YouTubeID != string.Empty && !playListYouTube.Contains(story.YouTubeID))
                        playListYouTube.Add(story.YouTubeID);
                    songNumber++;
                }

                #endregion

                if (playlistUrl.Length > 1)
                {
                    viewData.PlaylistUrl = playlistUrl.Remove(playlistUrl.Length - 1, 1);
                    viewData.PlaylistTitle = playlistTitle.Remove(playlistTitle.Length - 1, 1); ;
                }
                viewData.PlayListYouTube = playListYouTube;
            }

            return viewData;
        }

        private StoryListBySearchData FillSongsForMp3Player(StoryListBySearchData viewData)
        {
            viewData.PlayListYouTube = new List<string>();

            string playlistUrl = string.Empty;
            string playlistTitle = string.Empty;
            List<string> playListYouTube = new List<string>();

            int songNumber = 0;
            int mp3Number = 0;
            if (viewData.Stories.Length > 0)
            {
                #region First Song And Youtube Clip

                if (viewData.Stories[0].Mp3Files != null && viewData.Stories[0].Mp3Files.Length > 0)
                {
                    playlistUrl = "/Song/GetStreamMp3/" + viewData.Stories[0].Mp3Files[0].Mp3File_ID.ToString() + "/" + viewData.Stories[0].ID.ToString() + "|";
                    playlistTitle = WebHelper.RemoveSpecialCharactersExceptTire(viewData.Stories[0].Mp3Files[0].Title) + "|";
                    songNumber++;
                    mp3Number++;
                }
                if (viewData.Stories[0].YouTubeID != null && viewData.Stories[0].YouTubeID != string.Empty && !playListYouTube.Contains(viewData.Stories[0].YouTubeID))
                    playListYouTube.Add(viewData.Stories[0].YouTubeID);
                #endregion

                #region Adds all other songs to their playlists.

                foreach (var story in viewData.Stories)
                {
                    if (story.Mp3Files != null && story.Mp3Files.Length > 0 && songNumber > 1)
                    {
                        Mp3FileItem v = story.Mp3Files[0];//take first
                        playlistUrl = playlistUrl + "/Song/GetStreamMp3/" + v.Mp3File_ID.ToString() + "/" + story.ID.ToString() + "|";
                        playlistTitle = playlistTitle + WebHelper.RemoveSpecialCharactersExceptTire(v.Title) + "|";
                        mp3Number++;
                    }
                    if (story.YouTubeID != null && story.YouTubeID != string.Empty && !playListYouTube.Contains(story.YouTubeID))
                        playListYouTube.Add(story.YouTubeID);
                    songNumber++;
                }

                #endregion

                if (playlistUrl.Length > 1)
                {
                    viewData.PlaylistUrl = playlistUrl.Remove(playlistUrl.Length - 1, 1);
                    viewData.PlaylistTitle = playlistTitle.Remove(playlistTitle.Length - 1, 1); ;
                }
                viewData.PlayListYouTube = playListYouTube;
            }
            viewData.Mp3Count = mp3Number;
            // to do for now leave
            viewData.StoryCount = playListYouTube.Count;
            return viewData;
        }

        [OutputCache(Duration = Int32.MaxValue, VaryByParam = "none")]
        public ContentResult Sitemap()
        {
            return Content(DataContext.Sitemap(), "text/xml");
        }


        /// <summary>
        /// List all upcoming stories regardless the category
        /// </summary>
        /// <param name="page">The page number (1 based). If not specifed then shows the first page.</param>
        [CompressFilter]
        public ActionResult Upcoming(int? page)
        {
            var viewData = GetStoryListViewData<StoryListByCategoryData>(page);
            int total;

            viewData.Stories = DataContext.GetUpcomingStories(CurrentUserId, CalculateStartIndex(page), _storyPerPage, out total);

            viewData = FillSongsForMp3Player(viewData);

            viewData.StoryCount = total;
            viewData.Category = "Recently searched";

            return View("Category", viewData);
        }

        /// <summary>
        /// List Stories for a specific tag
        /// </summary>
        /// <param name="name">The tag name. If the parameter is blank it redirect to category action.</param>
        /// <param name="page">The page number (1 based). If not specifed then shows the first page.</param>
        [CompressFilter]
        [OutputCache(Duration = Int32.MaxValue, VaryByParam = "name;page")]
        public ActionResult Tag(string name, int? page)
        {
            if (string.IsNullOrEmpty(name))
            {
                RedirectToAction("Category");
                return View();
            }

            name = name.UrlDecode();
            name = name.Replace("  ", " ");
            name = name.Replace(" ", " or ");
            var viewData = GetStoryListViewData<StoryListByTagData>(page);

            //Tag tag = DataContext.GetTagByName(name);
            int total = 0;


            //viewData.Stories = DataContext.GetStoriesForTag(CurrentUserId, tag.ID, CalculateStartIndex(page), _storyPerPage, out total);
            viewData.Stories = DataContext.GetStoriesForTag(CurrentUserId, name, CalculateStartIndex(page), _storyPerPage, out total);

            viewData.StoryCount = total;
            viewData.Tag = name;

            return View("Tag", viewData);
        }

        /// <summary>
        /// List Stories Posted by a Specific User
        /// </summary>
        /// <param name="name">The name of the user. If the parameter is blank it redirect to category action.</param>
        /// <param name="page">The page number (1 based). If not specifed then shows the first page.</param>
        [CompressFilter]
        [OutputCache(Duration = Int32.MaxValue, VaryByParam = "name;page")]
        public ActionResult PostedBy(string name, int? page)
        {
            if (string.IsNullOrEmpty(name))
            {
                RedirectToAction("Category");
                return View();
            }

            name = name.UrlDecode();
            var viewData = GetStoryListViewData<StoryListByUserData>(page);
            int total = 0;

            //MembershipUser user = UserManager.GetUser(name, false);

            //viewData.Stories = DataContext.GetStoriesPostedByUser(CurrentUserId, (Guid)user.ProviderUserKey, CalculateStartIndex(page), _storyPerPage, out total);

            viewData.Stories = DataContext.GetStoriesPostedByUser(CurrentUserId, name, CalculateStartIndex(page), _storyPerPage, out total);

            viewData.StoryCount = total;
            viewData.PostedBy = name;

            return View("PostedBy", viewData);
        }

        public string GetUserName()
        {
            return CurrentUserName;
        }

        //public ActionResult Search(string q, int? weight, string searchType)
        //{
        //    return RedirectToAction("SearchNew", "Song", new { q = q, weight=weight,searchType=searchType,songFormat=1 });
        //}
        /// <summary>
        /// Search the Stories
        /// </summary>
        /// <param name="q">The Search Query</param>
        /// <param name="page">The page number (1 based). If not specifed then shows the first page.</param>
        //[OutputCache(Duration = int.MaxValue, VaryByParam = "q;weight;searchType;songFormat;page")]
        [CompressFilter]
        public ActionResult Search(string q, int? weight, string searchType, int? songFormat, int? page)
        {

            int localPage = 0;
            if (songFormat != null)
                _songFormat = (int)songFormat;

            q = q.Replace("music", "");
            q = q.Replace("songs", "");
            q = q.Replace("song", "");

            if (page.HasValue)
                localPage = page.Value;

            if (weight != null)
            {
                if (weight <= 10) // relleay low weight
                    _weight = 1;
                else if (weight > 10 && weight <= 100)
                    _weight = (int)weight * 10;
                else if (weight > 100 && weight <= 30000)
                    _weight = (int)weight * 6;
                else if (weight > 30000 && weight <= 50000)
                    _weight = (int)weight * 5;
                else if (weight > 50000 && weight <= 60000)
                    _weight = (int)weight * 4;
                else if (weight > 60000)
                    _weight = (int)weight * 3;
            }
            else
                _weight = 15000;

            if (string.IsNullOrEmpty(q))
            {
                return RedirectToAction("CategoryWeather");
            }

            //q = q.UrlDecode();
            q = q.Trim();
            var viewData = GetStoryListViewData<StoryListBySearchData>(page);
            int total = 0;
            string logicalOperator = " or ";
            string moodList = string.Empty;
            viewData.StoryCount = 0;
            switch (searchType)
            {
                case "ArtistGroup":
                    return RedirectToAction("Index", "Artist", new { artistName = q });
                case "Song":
                    viewData.Stories = DataContext.SearchSong(CurrentUserId, q, CalculateStartIndex(page), 30, out total);
                    break;
                case "Mood":
                    string[] parts = q.Split(new string[] { " " }, StringSplitOptions.None);
                    string qSynonyms = string.Empty;
                    qSynonyms = FindSynonims(parts[0]);

                    parts = qSynonyms.Split(new string[] { " " }, StringSplitOptions.None);

                    for (int i = 0; i < parts.Length; i++)
                    {
                        if (parts[i] != string.Empty && parts[i].ToLower() != "and" && parts[i].ToLower() != "or")
                        {
                            if (i == parts.Length - 1)//Last circle
                                logicalOperator = string.Empty;
                            moodList = moodList + parts[i] + logicalOperator;
                        }
                    }

                    if (songFormat != null)
                    {
                        if (songFormat == 2) // audio and video
                            viewData.Stories = DataContext.SearchMoodsVideo(moodList, _weight, CurrentUserId, localPage, _storyPerPage, out total);
                        else
                            viewData.Stories = DataContext.SearchMoods(moodList, _weight, CurrentUserId, localPage, _storyPerPage, out total);
                    }
                    else
                        viewData.Stories = DataContext.SearchMoods(moodList, _weight, CurrentUserId, localPage, _storyPerPage, out total);

                    viewData.StoryCount = total;
                    viewData.SearchQuery = q;
                    viewData.SearchType = searchType;
                    viewData = FillSongsForMp3Player(viewData);

                    return View("SearchMoods", viewData);
                case "Expression":
                    string[] parts2 = q.Split(new string[] { " " }, StringSplitOptions.None);

                    for (int i = 0; i < parts2.Length; i++)
                    {
                        if (parts2[i] != string.Empty && parts2[i].ToLower() != "and" && parts2[i].ToLower() != "or")
                        {
                            if (i == parts2.Length - 1)//Last circle
                                logicalOperator = string.Empty;
                            moodList = moodList + parts2[i] + logicalOperator;
                        }
                    }
                    viewData.Stories = DataContext.GetStoriesForTag(CurrentUserId, moodList, localPage, _storyPerPage, out total);
                    break;
                default:
                    return RedirectToAction("CategoryWeather");
            }



            viewData.SearchQuery = q;
            viewData.SearchType = searchType;
            viewData = FillSongsForMp3Player(viewData);
            return View("Search", viewData);
        }

        /// <summary>
        /// Use dictionary api to genarate more words
        /// </summary>
        /// <param name="q"></param>
        /// <returns></returns>
        private string FindSynonims(string q)
        {
            string url = @"http://api-pub.dictionary.com/v001?vid=sujba6m9s7erisn418y1oyeulxng2hivb26m8sv1z9&q=" + q + "&type=synonyms";
            string xml = WebHelper.GetResponseStandard(url);
            if (xml == null)
                return q;
            else
            {
                XmlDocument xmlDoc = new XmlDocument();

                xmlDoc.Load(new StringReader(xml));

                if (xmlDoc != null)
                {
                    foreach (XmlElement element in xmlDoc.GetElementsByTagName("headword"))
                    {
                        q = q + " " + element.InnerText;
                    }
                }
                return q;
            }
        }



        /// <summary>
        /// View the detail of the specified story.
        /// </summary>
        /// <param name="id">The story id (Mandatory).</param>
        [CompressFilter]
        public ActionResult Detail(int id)
        {
            int mp3Counter = 1;
            var viewData = GetViewData<StoryDetailData>();

            StoryDetailItem storyDetailItem = DataContext.Detail(CurrentUserId, id);
            storyDetailItem.searchString = (storyDetailItem.ArtistName + " " + storyDetailItem.Title).Replace(" ", "%20");

            if (storyDetailItem != null)
            {
                storyDetailItem.Playlist = new Mp3SongBin();
                storyDetailItem.PlayListYouTube = new List<string>();

                #region First Song And Youtube Clip

                if (storyDetailItem.Mp3Files.Length > 0)
                {
                    storyDetailItem.Playlist.Url = "/Song/GetStreamMp3/" + storyDetailItem.Mp3Files[0].Mp3File_ID.ToString() + "/" + storyDetailItem.ID.ToString() + "|";
                    //storyDetailItem.Playlist.Url = storyDetailItem.Mp3Files[0].Url + "|";
                    storyDetailItem.Playlist.Title = WebHelper.RemoveSpecialCharactersExceptTire(storyDetailItem.Mp3Files[0].Title) + "|";
                }
                if (storyDetailItem.YouTubeID != null || storyDetailItem.YouTubeID != string.Empty)
                {
                    storyDetailItem.PlayListYouTube.Add(storyDetailItem.YouTubeID);
                }

                #endregion

                #region Adds all other songs to their playlists.

                storyDetailItem.mp3URLs = new List<string>();

                //StringBuilder sb = new StringBuilder();

                foreach (SongSmallBin songSmallBin in storyDetailItem.Songs)
                {
                    if (songSmallBin.MP3FileID != null && songSmallBin.MP3FileID != 0 && (mp3Counter++) < 100)
                    {
                        storyDetailItem.Playlist.Url = storyDetailItem.Playlist.Url + "/Song/GetStreamMp3/" + songSmallBin.MP3FileID.ToString() + "/" + songSmallBin.StoryID.ToString() + "|";
                        //storyDetailItem.Playlist.Url = storyDetailItem.Playlist.Url + songSmallBin.mp3 + "|";
                        storyDetailItem.Playlist.Title = storyDetailItem.Playlist.Title + WebHelper.RemoveSpecialCharactersExceptTire(songSmallBin.name) + "|";
                        storyDetailItem.mp3URLs.Add(songSmallBin.mp3);
                    }

                    if (storyDetailItem.YouTubeID != null || storyDetailItem.YouTubeID != string.Empty && !storyDetailItem.PlayListYouTube.Contains(songSmallBin.YouTubeID))
                        storyDetailItem.PlayListYouTube.Add(songSmallBin.YouTubeID);
                }

                #endregion

                viewData.Story = storyDetailItem;

                return View("Detail", viewData);
            }
            else
                return View("NotFound", viewData);
        }

        /// <summary>
        /// Submits a Story.The user must be authenticated prior calling this method.
        /// This is an Ajax Operation.
        /// </summary>
        [CompressFilter]
        public ActionResult Submit(string songTitle, int storyCategoryId, string storyDescription, string artistName)
        {
            //discogsApi.SearchArtist("");

            //DiscogsAPI.ResponseClasses.ArtistRequest.resp discoApi = DiscogsAPI.Discogs.SearchArtist("muse");

            //string ime = discoApi.artist.name;

            songTitle = songTitle.Replace("amp;", "&");
            artistName = artistName.Replace("amp;", "&");

            string encodingCode = string.Empty;
            string tags = string.Empty;
            string videoID = string.Empty;
            string imageURL = string.Empty;
            string youTubeDescrption = string.Empty;
            bool hasImage = false;


            var result = new JsonResult();

            if (!IsUserAuthenticated)
            {
                result.errorMessage = "You are not authenticated to call this method.";
            }
            else if (string.IsNullOrEmpty(songTitle))
            {
                result.errorMessage = "Song title cannot be blank.";
            }
            else if (string.IsNullOrEmpty(artistName))
            {
                result.errorMessage = "Artist name cannot be blank.";
            }
            else if (string.IsNullOrEmpty(storyDescription))
            {
                result.errorMessage = "Song description cannot be blank.";
            }
            else
            {
                try
                {
                    YouTubeApi youTube = new YouTubeApi();
                    Mp3FileApi mp3FileApi = new Mp3FileApi();

                    youTube.GetYouTubeVideo(songTitle, artistName, ref encodingCode, ref videoID, ref tags, ref youTubeDescrption);

                    DataContext.SubmitStory(songTitle, artistName, storyCategoryId, storyDescription, tags, mp3FileApi.GetMp3Urls(artistName, songTitle), videoID, CurrentUserId, youTubeDescrption);

                    result.isSuccessful = true;
                }
                catch (InvalidOperationException e)
                {
                    result.errorMessage = e.Message;
                }
            }

            return View("Json", result);
        }

        /// <summary>
        /// Deletes a specific story from the database based on the id
        /// </summary>
        /// <returns></returns>
        [CompressFilter]
        [RequiresRole(RoleToCheckFor = "Administrator")]
        public ActionResult DeleteStory(int storyId)
        {
            DataContext.DeleteStory(storyId);
            return RedirectToAction("Category");
        }

        #region Cms begin

        [CompressFilter]
        [OutputCache(Duration = int.MaxValue, VaryByParam = "none")]
        public ActionResult Privacy()
        {
            var viewData = GetViewData<CMSData>();
            return View("Privacy", viewData);
        }

        [CompressFilter]
        [OutputCache(Duration = int.MaxValue, VaryByParam = "none")]
        public ActionResult License()
        {
            var viewData = GetViewData<CMSData>();
            return View("License", viewData);
        }


        [RequiresRole(RoleToCheckFor = "Administrator")]
        [CompressFilter]
        public ActionResult Administration()
        {
            var viewData = GetViewData<CMSData>();

            return View("Administration", viewData);
        }

        [RequiresRole(RoleToCheckFor = "Administrator")]
        [CompressFilter]
        public ActionResult NewsEdit()
        {
            string type = "News";
            var viewData = GetViewData<CMSData>();
            viewData.Value = DataContext.GetValue(type);
            return View("NewsEdit", viewData);
        }

        [CompressFilter]
        public ActionResult News()
        {
            string type = "News";
            var viewData = GetViewData<CMSData>();
            viewData.Value = DataContext.GetValue(type);
            return View("News", viewData);
        }
        [RequiresRole(RoleToCheckFor = "Administrator")]
        [CompressFilter]
        public ActionResult SaveNews(string tekstarea)
        {
            string type = "News";
            DataContext.SubmitText(type, tekstarea);
            return RedirectToAction("NewsEdit");
        }
        [RequiresRole(RoleToCheckFor = "Administrator")]
        [CompressFilter]
        public ActionResult AboutEdit()
        {
            string type = "About";

            var viewData = GetViewData<CMSData>();

            viewData.Value = DataContext.GetValue(type);


            return View("AboutEdit", viewData);


        }

        [CompressFilter]
        [OutputCache(Duration = int.MaxValue, VaryByParam = "none")]
        public ActionResult About()
        {
            var viewData = GetViewData<CMSData>();
            return View("About", viewData);
        }

        [RequiresRole(RoleToCheckFor = "Administrator")]
        [CompressFilter]
        [HttpPost, ValidateInput(false)]
        public ActionResult SaveAbout(string tekstarea)
        {
            string type = "About";
            DataContext.SubmitText(type, tekstarea);
            return RedirectToAction("AboutEdit");
        }
        // Contact cms begin
        [RequiresRole(RoleToCheckFor = "Administrator")]
        [CompressFilter]
        [HttpPost, ValidateInput(false)]
        public ActionResult ContactEdit()
        {
            string type = "Contact";
            var viewData = GetViewData<CMSData>();
            viewData.Value = DataContext.GetValue(type);
            return View("ContactEdit", viewData);
        }

        [OutputCache(Duration = int.MaxValue, VaryByParam = "none")]
        [CompressFilter]
        public ActionResult Contact()
        {
            var viewData = GetViewData<CMSData>();
            return View("Contact", viewData);
        }
        [RequiresRole(RoleToCheckFor = "Administrator")]
        [CompressFilter]
        [HttpPost, ValidateInput(false)]
        public ActionResult SaveContact(string tekstarea)
        {
            string type = "Contact";
            DataContext.SubmitText(type, tekstarea);
            return RedirectToAction("ContactEdit");
        }
        // Contact end
        #endregion Cms end

        /// <summary>
        /// Love the Story. The user must be authenticated prior calling this method.
        /// This is an Ajax Operation.
        /// </summary>
        /// <param name="storyId">The story id(Mandatory).</param>
        public ActionResult Love(int storyId)
        {
            var result = new JsonResult();
            if (!IsUserAuthenticated)
            {
                result.errorMessage = "You are not authenticated to call this method.";
            }
            else
            {
                try
                {
                    DataContext.LoveStory(storyId, CurrentUserId, _qualifyingLove);
                    result.isSuccessful = true;
                }
                catch (InvalidOperationException e)
                {
                    result.errorMessage = e.Message;
                }
            }

            return View("Json", result);
        }

        /// <summary>
        /// Post Comment for the specified story. The user must be authenticated prior calling this method.
        /// This is an Ajax Operation.
        /// </summary>
        /// <param name="storyId">The story id (Mandatory).</param>
        /// <param name="commentContent">Content of the comment (Mandatory).</param>
        /// 
        [CompressFilter]
        public ActionResult Comment(int storyId, string commentContent)
        {

            var result = new JsonResult();

            if (!IsUserAuthenticated)
            {
                result.errorMessage = "You are not authenticated to call this method.";
            }
            else if (string.IsNullOrEmpty(commentContent))
            {
                result.errorMessage = "Comment cannot be blank.";
            }
            else
            {
                try
                {
                    DataContext.PostComment(storyId, CurrentUserId, commentContent);
                    result.isSuccessful = true;
                }
                catch (InvalidOperationException e)
                {
                    result.errorMessage = e.Message;
                }
            }

            return View("Json", result);

        }

        public ActionResult GetStreamMp3Old(int mp3FileID, int storyID)
        {
            string fileName = "empty.mp3";
            string dirDetails = Server.MapPath("/download/documents/");
            string emptyPath = Path.Combine(dirDetails, fileName);

            MP3FILE mp3File = DataContext.GetMp3UrlByID(mp3FileID);
            WebClient urlGrabber = new WebClient();
            Stream stream;
            FileStreamResultNew fileStreamResult;
            string contentType = string.Empty;
            urlGrabber.Proxy = null;
            urlGrabber.Encoding = System.Text.Encoding.UTF8;
            urlGrabber.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

            try
            {
                if (mp3File.url.IndexOf("4shared") != -1)
                {
                    #region 4Shared

                    urlGrabber.Dispose();
                    urlGrabber = new WebClient();
                    string newUrl = WebHelper.GetNewUrl4Shared(mp3File.url);

                    // Implement a 11 second wait between requests
                    Thread.Sleep(11000);

                    stream = urlGrabber.OpenRead(newUrl);

                    contentType = urlGrabber.ResponseHeaders["Content-Type"];
                    if (
                    "audio/mpeg" == contentType ||
                    "audio/mpeg3" == contentType ||
                    "audio/x-mpeg-3" == contentType ||
                    "video/mpeg" == contentType ||
                    "video/x-mpeg" == contentType ||
                    "APPLICATION/OCTET-STREAM" == contentType
                    )
                    {
                        fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                        fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                        fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                        fileStreamResult.BufferOutput = false;
                        return fileStreamResult;
                    }
                    else
                    {// try second time from 4shared
                        newUrl = WebHelper.GetNewUrl4Shared(newUrl);
                        // Implement a 20 second wait between requests
                        Thread.Sleep(21000);

                        stream = urlGrabber.OpenRead(newUrl);
                        contentType = urlGrabber.ResponseHeaders["Content-Type"];
                        if (
                        "audio/mpeg" == contentType ||
                        "audio/mpeg3" == contentType ||
                        "audio/x-mpeg-3" == contentType ||
                        "video/mpeg" == contentType ||
                        "video/x-mpeg" == contentType ||
                        "APPLICATION/OCTET-STREAM" == contentType
                        )
                        {
                            fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                            fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                            fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                            fileStreamResult.BufferOutput = false;
                            return fileStreamResult;
                        }
                    }

                    #endregion
                }
                else
                    stream = urlGrabber.OpenRead(mp3File.url);


                contentType = urlGrabber.ResponseHeaders["Content-Type"];
                if (
                    "audio/mpeg" == contentType ||
                    "audio/mpeg3" == contentType ||
                    "audio/x-mpeg-3" == contentType ||
                    "video/mpeg" == contentType ||
                    "video/x-mpeg" == contentType ||
                    "APPLICATION/OCTET-STREAM" == contentType
                    )
                {
                    fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                    fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                    fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                    fileStreamResult.BufferOutput = false;
                    return fileStreamResult;
                }
                else
                {
                    mp3File.IsValid = false;
                    DataContext.Save();
                    if (System.IO.File.Exists(emptyPath))
                    {
                        return base.File(emptyPath, "audio/mpeg3");
                    }
                }
            }
            catch (Exception ex)
            {
                //throw new ApplicationException(ex.StackTrace);
                TraceLog.TimeWrite(ex, "GetStreamMp3() mp3File ID=" + mp3File.MP3_FILEIDZ + " is disabled.Title=" + mp3File.Title);
                mp3File.IsValid = false;
                DataContext.Save();
                if (System.IO.File.Exists(emptyPath))
                {
                    return base.File(emptyPath, "audio/mpeg3");
                }
            }

            if (System.IO.File.Exists(emptyPath))
            {
                return base.File(emptyPath, "audio/mpeg3");
            }

            return RedirectToAction("Detail", new { id = storyID });
        }

        public ActionResult GetStreamMp3New(int mp3FileID, int storyID)
        {
            MP3FILE mp3File = DataContext.GetMp3UrlByID(mp3FileID);
            return View(mp3File.url);
        }

        public ActionResult GetStreamMp3Backup(int mp3FileID, int storyID)
        {
            MP3FILE mp3File = DataContext.GetMp3UrlByID(mp3FileID);
            WebClient urlGrabber = new WebClient();
            Stream stream;
            FileStreamResultNew fileStreamResult;
            string contentType = string.Empty;
            urlGrabber.Proxy = null;
            urlGrabber.Encoding = System.Text.Encoding.UTF8;
            urlGrabber.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

            try
            {
                if (mp3File.url.IndexOf("4shared") != -1)
                {
                    #region 4Shared

                    urlGrabber.Dispose();
                    urlGrabber = new WebClient();
                    string newUrl = WebHelper.GetNewUrl4Shared(mp3File.url);

                    // Implement a 11 second wait between requests
                    Thread.Sleep(11000);

                    stream = urlGrabber.OpenRead(newUrl);

                    contentType = urlGrabber.ResponseHeaders["Content-Type"];
                    if (
                    "audio/mpeg" == contentType ||
                    "audio/mpeg3" == contentType ||
                    "audio/x-mpeg-3" == contentType ||
                    "video/mpeg" == contentType ||
                    "video/x-mpeg" == contentType ||
                    "APPLICATION/OCTET-STREAM" == contentType
                    )
                    {
                        fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                        fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                        fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                        fileStreamResult.BufferOutput = false;
                        return fileStreamResult;
                    }
                    else
                    {// try second time from 4shared
                        newUrl = WebHelper.GetNewUrl4Shared(newUrl);
                        // Implement a 20 second wait between requests
                        Thread.Sleep(21000);

                        stream = urlGrabber.OpenRead(newUrl);
                        contentType = urlGrabber.ResponseHeaders["Content-Type"];
                        if (
                        "audio/mpeg" == contentType ||
                        "audio/mpeg3" == contentType ||
                        "audio/x-mpeg-3" == contentType ||
                        "video/mpeg" == contentType ||
                        "video/x-mpeg" == contentType ||
                        "APPLICATION/OCTET-STREAM" == contentType
                        )
                        {
                            fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                            fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                            fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                            fileStreamResult.BufferOutput = false;
                            return fileStreamResult;
                        }
                    }

                    #endregion
                }
                else
                    stream = urlGrabber.OpenRead(mp3File.url);


                contentType = urlGrabber.ResponseHeaders["Content-Type"];
                if (
                    "audio/mpeg" == contentType ||
                    "audio/mpeg3" == contentType ||
                    "audio/x-mpeg-3" == contentType ||
                    "video/mpeg" == contentType ||
                    "video/x-mpeg" == contentType ||
                    "APPLICATION/OCTET-STREAM" == contentType
                    )
                {
                    fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                    fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                    fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                    fileStreamResult.BufferOutput = false;
                    return fileStreamResult;
                }
                else
                {
                    //mp3File.IsValid = false;
                    //DataContext.Save();
                    if (mp3File != null)
                        DataContext.DeleteMp3(mp3File);
                    return RedirectToAction("EmptyMp3", new { mp3File = mp3File });
                }
            }
            catch (Exception ex)
            {
                //mp3File.IsValid = false;
                //DataContext.Save();
                if (mp3File != null)
                    DataContext.DeleteMp3(mp3File);
                return RedirectToAction("EmptyMp3", new { mp3File = mp3File });
            }
        }

        public ActionResult GetStreamMp3(int mp3FileID, int storyID)
        {
            List<MP3FILE> mp3Files = DataContext.Getallmp3(storyID);
            int listForDeleting = 0;
            WebClient urlGrabber = new WebClient();
            Stream stream;
            FileStreamResultNew fileStreamResult;
            string contentType = string.Empty;
            urlGrabber.Proxy = null;
            urlGrabber.Encoding = System.Text.Encoding.UTF8;
            urlGrabber.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

            foreach (MP3FILE mp3File in mp3Files)
            {
                if (mp3File.Title.ToLower().IndexOf("mix") == -1)
                {
                    if (mp3File.url.ToLower().IndexOf("remix") != -1 || mp3File.url.ToLower().IndexOf("mix") != -1) // Jump the remix songs. 
                        break;
                }

                try
                {
                    if (mp3File.url.IndexOf("4shared") != -1)
                    {
                        #region 4Shared

                        urlGrabber.Dispose();
                        urlGrabber = new WebClient();
                        string newUrl = WebHelper.GetNewUrl4Shared(mp3File.url);

                        // Implement a 11 second wait between requests
                        Thread.Sleep(11000);

                        stream = urlGrabber.OpenRead(newUrl);

                        contentType = urlGrabber.ResponseHeaders["Content-Type"];
                        if (
                        "audio/mpeg" == contentType ||
                        "audio/mpeg3" == contentType ||
                        "audio/x-mpeg-3" == contentType ||
                        "video/mpeg" == contentType ||
                        "video/x-mpeg" == contentType ||
                        "APPLICATION/OCTET-STREAM" == contentType
                        )
                        {
                            fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                            fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                            fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                            fileStreamResult.BufferOutput = false;
                            if (listForDeleting > 0)
                                DataContext.Save();
                            return fileStreamResult;
                        }
                        else
                        {// try second time from 4shared
                            newUrl = WebHelper.GetNewUrl4Shared(newUrl);
                            // Implement a 20 second wait between requests
                            Thread.Sleep(21000);

                            stream = urlGrabber.OpenRead(newUrl);
                            contentType = urlGrabber.ResponseHeaders["Content-Type"];
                            if (
                            "audio/mpeg" == contentType ||
                            "audio/mpeg3" == contentType ||
                            "audio/x-mpeg-3" == contentType ||
                            "video/mpeg" == contentType ||
                            "video/x-mpeg" == contentType ||
                            "APPLICATION/OCTET-STREAM" == contentType
                            )
                            {
                                fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                                fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                                fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                                fileStreamResult.BufferOutput = false;
                                if (listForDeleting > 0)
                                    DataContext.Save();
                                return fileStreamResult;
                            }
                            else
                            {
                                if (mp3File != null)
                                {
                                    listForDeleting++;
                                    DataContext.DeleteMp3(mp3File);
                                }
                            }
                        }

                        #endregion
                    }
                    else
                        stream = urlGrabber.OpenRead(mp3File.url);


                    contentType = urlGrabber.ResponseHeaders["Content-Type"];
                    if (
                        "audio/mpeg" == contentType ||
                        "audio/mpeg3" == contentType ||
                        "audio/x-mpeg-3" == contentType ||
                        "video/mpeg" == contentType ||
                        "video/x-mpeg" == contentType ||
                        "APPLICATION/OCTET-STREAM" == contentType
                        )
                    {
                        fileStreamResult = new FileStreamResultNew(stream, urlGrabber.ResponseHeaders["Content-Type"]);
                        fileStreamResult.FileSize = long.Parse(urlGrabber.ResponseHeaders["Content-Length"]);
                        fileStreamResult.FileDownloadName = mp3File.Title + "[www.ILoveThisMusic.com].mp3";
                        fileStreamResult.BufferOutput = false;
                        // Delete invalid mp3 songs in one turn.
                        if (listForDeleting > 0)
                            DataContext.Save();

                        if (fileStreamResult.FileSize > 508190)
                            return fileStreamResult;
                        else
                        {
                            if (mp3File != null)
                            {
                                listForDeleting++;
                                DataContext.DeleteMp3(mp3File);
                            }
                        }
                    }
                    else
                    {
                        if (mp3File != null)
                        {
                            listForDeleting++;
                            DataContext.DeleteMp3(mp3File);
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (mp3File != null)
                    {
                        listForDeleting++;
                        DataContext.DeleteMp3(mp3File);
                    }
                }
            }
            // Delete invalid mp3 songs in one turn.
            if (listForDeleting > 0)
            {
                DataContext.Save();
            }
            //If it gets to the end finish
            return RedirectToAction("EmptyMp3");
        }

        [CompressFilter]
        public ActionResult EmptyMp3()
        {
            string fileName = "empty.mp3";
            string dirDetails = Server.MapPath("/download/documents/");
            string emptyPath = Path.Combine(dirDetails, fileName);

            if (System.IO.File.Exists(emptyPath))
            {
                return base.File(emptyPath, "audio/mpeg3");
            }
            else
                return null;
        }

        [CompressFilter]
        [OutputCache(Duration = int.MaxValue, VaryByParam = "imageName")]
        public ActionResult ImageStatic(string imageName, int width, int height)
        {
            string dirDetails = Server.MapPath("/download/images/");
            string errorPath = Path.Combine(dirDetails, "error.gif");
            try
            {
                string extension = imageName.Split(new string[] { "." }, StringSplitOptions.None)[1];
                string imageDir = "~/Views/Images/";
                string path = Path.Combine(imageDir, imageName);

                if (!System.IO.File.Exists(path))
                    return base.File(path, "image/" + extension);
                else
                    return base.File(errorPath, "image/gif");
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "ImageStatic exception");
                return base.File(errorPath, "image/gif");
            }
        }

        /// <summary>
        /// Serves all dynamic images, either from hosting or it downloads it from internet
        /// </summary>
        /// <param name="id"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        [CompressFilter]
        [OutputCache(Duration = int.MaxValue, VaryByParam = "id")]
        public ActionResult Image(int id, int width, int height)
        {
            string dirDetails = Server.MapPath("/download/images/");
            string dirThumbsCategories = Server.MapPath("/download/imagesThumbsCategories/");
            string errorPath = Path.Combine(dirDetails, "error.gif");

            if (width != 250)
                dirDetails = dirThumbsCategories;
            if (width < 85)
                width = 85;
            if (height < 70)
                height = 70;
            try
            {
                IMAGE image = DataContext.GetImage(id);
                string fileName = Path.Combine(dirDetails, image.IMAGE_IDZ + ".jpg");
                string path = Path.Combine(dirDetails, image.IMAGE_IDZ + ".jpg");

                if (!System.IO.File.Exists(path))
                {// Download image 
                    Bitmap downloadedImage = LoadImageFromURL(image.URL);
                    System.Drawing.Image objThumbnail = downloadedImage.GetThumbnailImage(width, height, null, System.IntPtr.Zero);
                    objThumbnail.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                return base.File(path, "image/jpeg");
            }
            catch (Exception ex)
            {
                TraceLog.TimeWrite(ex, "Image exception");
                return base.File(errorPath, "image/gif");
            }
        }

        #region Utility

        /// <summary>
        /// Return number of moods to add for the category
        /// </summary>
        /// <param name="category"></param>
        /// <returns></returns>
        private int GetCategoryNumber(string category)
        {
            switch (category)
            {
                case "ROCK":
                    return 2; //2
                case "RAP":
                    return 5;//5
                case "POP":
                    return 3;//3
                case "REGGAE":
                    return 6;
                case "SKA":
                    return 6;
                case "JAZZfwsBLUES":
                    return 6;
                case "RampB":
                    return 3;//3
                case "INTER":
                    return 6;
                case "OTHER":
                    return 5;//5
                case "DNB":
                    return 6;
                case "TRANCE":
                    return 6;
                case "HOUSE":
                    return 3;//3
                case "CHILL_OUT":
                    return 6;
                case "CLASSICAL":
                    return 6;
            }
            return -1;
        }

        private Bitmap LoadImageFromURL(string URL)
        {
            const int BYTESTOREAD = 10000;
            Bitmap Img;
            WebRequest myRequest = WebRequest.Create(URL);

            WebResponse myResponse = myRequest.GetResponse();
            Stream ReceiveStream = myResponse.GetResponseStream();
            BinaryReader br = new BinaryReader(ReceiveStream);
            MemoryStream memstream = new MemoryStream();
            byte[] bytebuffer = new byte[BYTESTOREAD];
            int BytesRead = br.Read(bytebuffer, 0, BYTESTOREAD);
            while (BytesRead > 0)
            {
                memstream.Write(bytebuffer, 0, BytesRead);
                BytesRead = br.Read(bytebuffer, 0, BYTESTOREAD);
            }
            Img = new Bitmap(memstream);

            //   memstream.Close();
            br.Close();
            ReceiveStream.Close();
            myResponse.Close();
            myRequest.Abort();
            return Img;
        }

        private T GetStoryListViewData<T>(int? page) where T : BaseStoryListData, new()
        {
            var viewData = GetViewData<T>();
            viewData.CurrentPage = page.HasValue ? page.Value : 1;
            viewData.StoryPerPage = _storyPerPage;
            viewData.SongFormat = _songFormat;

            return viewData;
        }

        [OutputCache(Duration = Int32.MaxValue, VaryByParam = "none")]
        private T GetViewData<T>() where T : BaseViewData, new()
        {
            var viewData = new T
            {
                IsAuthenticated = IsUserAuthenticated,
                UserName = CurrentUserName,
                Categories = DataContext.GetCategories(),
                Tags = DataContext.GetTags(_topTags),
                AllMoods = DataContext.AllMoods(),
                RandArtists = DataContext.Get50Artist(),
                RandSong = DataContext.Get50Songs(),

            };

            return viewData;
        }

        /// <summary>
        /// Calculates the start index becouse it needs to return 
        /// specified number of stories for one page
        /// Example 10 max to show in one page :)
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        private static int CalculateStartIndex(int? page)
        {
            if (page.HasValue)
            {
                if (page.Value > 1)
                {
                    return ((page.Value - 1) * _storyPerPage);
                }
            }

            return 0;
        }

        private static bool IsValidUrl(string url)
        {
            return UrlExpression.IsMatch(url);
        }


        #endregion
    }
}